package com.seguridad.txwrapping.tester;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;

import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;


public class WSSWOptionalTester extends WSSWTester {

	public WSSWOptionalTester(URL endpoint, String validMessagePath, String elementName) {
		super(endpoint, validMessagePath, elementName);
	}

	@Override
	protected String sampleWrapped() {
		logger.debug("########## SAMPLE OPTIONAL");
		String hash = null;
		SOAPConnection connection = null;
		InputStream is = null;
		try {
			is = new FileInputStream(getValidMessagePath());
			SOAPConnectionFactory sfc = SOAPConnectionFactory.newInstance();
			connection = sfc.createConnection();
			
			MessageFactory mf = MessageFactory.newInstance();
			SOAPMessage sm = mf.createMessage(null, is);
			
			// 1 - Buscar el elemento a wrappear
			Node originalNode = searchNodeToWrap(sm);
			// 2 - Crear el wrapper sobre el elemento
			wrapOptionalElement(sm, originalNode);

			if(logger.isDebugEnabled()){
				logger.debug("REQUEST");
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				sm.writeTo(baos);
				logger.debug(baos.toString());
			}
			
			SOAPMessage response = connection.call(sm, getEndpoint());
			
			if(logger.isDebugEnabled()){
				logger.debug("RESPONSE");
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				response.writeTo(baos);
				logger.debug(baos.toString());
			}
			
			hash = hashBody(response);
			
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			try {
				if(connection != null) {connection.close();}
				if(is != null) {is.close();}
			} catch (SOAPException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return hash;
	}

	private void wrapOptionalElement(SOAPMessage sm, Node originalNode) {
		try {
			// Saca el nodo a wrappear del documento
			Node parent = originalNode.getParentNode();
			parent.removeChild(originalNode);	
			// Crea el wrapper
			String nsPrefix = sm.getSOAPPart().getEnvelope().getPrefix();
			Element wrapNode = sm.getSOAPPart().createElement("Wrapper");
			wrapNode.setAttribute(nsPrefix + ":mustUnderstand", "0");
			wrapNode.setAttribute(nsPrefix + ":role", ".../none");
			// Pone el nodo a wrappear dentro del wrapper
			wrapNode.appendChild(originalNode);
			
			// Pone el wrapper en el header
			sm.getSOAPHeader().appendChild(wrapNode);
		} catch (DOMException e) {
			e.printStackTrace();
		} catch (SOAPException e) {
			e.printStackTrace();
		}
	}

}
